﻿// //   Copyright 2007-2011 Comdiv (F. Sadykov) - http://code.google.com/u/fagim.sadykov/
// //   Supported by Media Technology LTD 
// //    
// //   Licensed under the Apache License, Version 2.0 (the "License");
// //   you may not use this file except in compliance with the License.
// //   You may obtain a copy of the License at
// //    
// //        http://www.apache.org/licenses/LICENSE-2.0
// //    
// //   Unless required by applicable law or agreed to in writing, software
// //   distributed under the License is distributed on an "AS IS" BASIS,
// //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// //   See the License for the specific language governing permissions and
// //   limitations under the License.
// //   
// //   MODIFICATIONS HAVE BEEN MADE TO THIS FILE

using System;
using System.Security.Principal;
using Comdiv.QWeb.Utils;

namespace Comdiv.QWeb.Security {
	internal class DefaultActionAuthorizer : IActionAuthorizer, IRegistryBound {
		private readonly SimpleActionRoleChecker checker = new SimpleActionRoleChecker();
		private QWebServiceRegistry _registry;
		private IPrincipalSource principalSource;
		private IRoleResolver roleResolver;

		#region IActionAuthorizer Members

		public AuthorizationResult Authorize(QWebContext context) {
			lock (this) {
				IPrincipal user = null;
				var renderAuthorized = true;
				var resolver = context.ActionDescriptor.Action != null && context.ActionDescriptor.Action is IRoleResolver
				               	? (IRoleResolver) context.ActionDescriptor.Action
				               	: roleResolver;
				if (context.RenderDescriptor.UseAuthorization) {
					renderAuthorized = false;
					var roles = context.RenderDescriptor.Role.split();
					if (0 == roles.Count || roles.Contains("DEFAULT")) renderAuthorized = true;

					else {
						user = principalSource.CurrentUser;
						if (resolver.IsInRole(user, "ADMIN", false, context)) return AuthorizationResult.OK;
						foreach (var role in roles) {
							if (resolver.IsInRole(user, role, false, context)) renderAuthorized = true;
						}
					}
				}
				if (!renderAuthorized)
					return AuthorizationResult.Error(new Exception("render role checking against current user don't match"));
				if (!(context.RenderDescriptor.OverrideActionAuthorization && context.RenderDescriptor.UseAuthorization)) {
					var roleresult = checker.IsAuthorized(Registry, user, context.ActionDescriptor, context, resolver);
					if (roleresult) return AuthorizationResult.OK;
				}
				else {
					return AuthorizationResult.OK;
				}
				return AuthorizationResult.Error(new Exception("action role checking against current user don't match"));
			}
		}

		#endregion

		#region IRegistryBound Members

		public void SetRegistry(QWebServiceRegistry registry) {
			_registry = registry;
			if (null == principalSource) principalSource = registry.PrincipalSource;
			if (null == roleResolver) roleResolver = registry.RoleResolver;
		}

		public QWebServiceRegistry Registry {
			get { return _registry; }
		}

		#endregion
	}
}